package cn.edu.zju.om.analyse;

import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;

public class PhraseGroup {
	
	private double[] groupCenter;
	
	boolean isChanged;
	
	List<PhraseFeatureVector> groupedPhrases;
	
	public PhraseGroup(PhraseFeatureVector vector) {
		groupCenter = vector.getFeatureVector().clone();
		isChanged = true;
		groupedPhrases = new LinkedList<PhraseFeatureVector>();
		
		groupedPhrases.add(vector);
	}
	
	public boolean isChanged() {
		return isChanged;
	}
	
	public void resetChangedFlag() {
		isChanged = false;
	}
	
	public List<PhraseFeatureVector> getGroupedPhrases() {
		return groupedPhrases;
	}
	
	public void addToGroup(PhraseFeatureVector vector) {
		groupedPhrases.add(vector);
		isChanged = true;
	}
	
	public void removeFromGroup(PhraseFeatureVector vector) {
		groupedPhrases.remove(vector);
		isChanged = true;
	}
	
	public void updateGroupCenter() throws Exception {
		if (!isChanged) {
			return;
		}
		
		Helper.assertFeatureVectors(groupedPhrases);
		
		for(int i = 0; i < groupCenter.length; ++i) {
			groupCenter[i] = 0;
		}
		
		Helper.assertFeatureVectors(groupedPhrases);
		
		for(PhraseFeatureVector vector : groupedPhrases) {
			double[] vectorArray = vector.getFeatureVector();
			
			Helper.assertFeatureVectors(groupedPhrases);
			
			for(int i = 0; i < vectorArray.length; ++i) {
				double number = vectorArray[i] / groupedPhrases.size();
				groupCenter[i] = groupCenter[i] + number;
			}
			
			Helper.assertFeatureVectors(groupedPhrases);
			
			Helper.assertArrayNoLessThanOne(vectorArray);
		}
		
//		for(int i = 0; i < groupCenter.length; ++i) {
//			/*if (groupedPhrases.size() == 0) {
//				continue;
//			}*/
//			groupCenter[i] /= groupedPhrases.size();
//		}
		
		Helper.assertArrayNoNaN(groupCenter);
		
		Helper.assertFeatureVectors(groupedPhrases);
		
		resetChangedFlag();
	}
	
	public double caculateDistance(PhraseFeatureVector vector) throws Exception {
		double[] featureVector = vector.getFeatureVector();
		
//		Helper.assertArrayNoNaN(featureVector);
//		Helper.assertArrayNoLessThanOne(featureVector);
////		
//		double squareSum = 0;
//		
//		for(int i =0; i < featureVector.length; ++i) {
//			squareSum += Math.pow(featureVector[i] - groupCenter[i], 2.0);
//		}
//		
//		if (Double.isNaN(squareSum)) {
//			System.out.println("NaN");
//		}
//		
//		return Math.sqrt(squareSum);
		
		
		
//		int hitCount = 0;
//		for(int i = 0; i < featureVector.length; ++i) {
//			if (featureVector[i] != 0 && groupCenter[i] != 0) {
//				hitCount++;
//			}
//		}
//		
//		return -hitCount;
		
		/////////////////////////////////////
		/// Cos
		////////////////////////////////////
		
//		double featureVectorMod = 0;
//		double groupCenterMod = 0;
//		double similarity = 0;
//		for(int i = 0; i < featureVector.length; ++i) {
//			
//			
//			featureVectorMod += Math.pow(featureVector[i], 2);
//			groupCenterMod += Math.pow(groupCenter[i], 2);
//		}
//		
//		featureVectorMod = Math.sqrt(featureVectorMod);
//		groupCenterMod = Math.sqrt(groupCenterMod);
//		
//		for(int i = 0; i < featureVector.length; ++i) {
//			similarity += featureVector[i] / featureVectorMod / groupCenterMod * groupCenter[i] ;
//			
//			if (Double.isNaN(similarity)) {
//				System.out.println("Nan");
//			}
//		}
//		
//		
//		
//		//double similarity = dotSum / featureVectorMod / groupCenterMod;
//		
//		System.out.println(groupCenter.toString());
//		System.out.println(featureVector.toString());
//		System.out.println(similarity);
//		
//		return -similarity;
		
		
		///////////////////////////////////////////
		// Pearson
		//////////////////////////////////////////
		double sum1 = 0;
		double sum2 = 0;
		
		double sum1Sq = 0;
		double sum2Sq = 0;
		
		double pSum =0;
		for(int i = 0; i < groupCenter.length; ++i) {
			sum1 += groupCenter[i];
			sum2 += featureVector[i];
			
			sum1Sq += Math.pow(groupCenter[i], 2);
			sum2Sq += Math.pow(featureVector[i], 2);
			
			pSum += groupCenter[i] * featureVector[i];
		}
		
		int n = groupCenter.length;
		
		double num = pSum-(sum1*sum2/n);
		double den=Math.sqrt((sum1Sq-Math.pow(sum1,2)/n)*(sum2Sq-Math.pow(sum2,2)/n));
		if (Double.compare(den, 0) == 0) {
			return 0;
		}

		return -num/den;
		
	}
	
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		Collections.sort(groupedPhrases, new Comparator<PhraseFeatureVector>() {
			public int compare(PhraseFeatureVector o1, PhraseFeatureVector o2) {
				return o2.getPhrase().getCount() - o1.getPhrase().getCount();
			}
		});
		for(PhraseFeatureVector phrase : groupedPhrases) {
			sb.append(String.format("%s : %d : %f, ", phrase.getPhraseHeadTerm(), phrase.getPhrase().getCount(), phrase.getPhrase().getAverageRating()));
			//sb.append(phrase.getPhraseHeadTerm() + " : " + phrase.getPhrase().getCount() + phrase.getPhrase().getAverageRating() + ", ");
		}
		return sb.toString();
	}

}
